import { ColliderComponent, Material, Mesh, ModelComponent, RigidBody, SphereCollider, Vec3 } from 'cc';
import { _decorator, Component, MeshRenderer, Node, Sprite, SpriteFrame } from 'cc';
import { ICollisionEvent } from 'cc';
import { App } from '../../App';
import { GameModel } from './model/GameModel';
import { BoxCollider } from 'cc';
import { director } from 'cc';
import { EventConst } from '../../common/Common';
import { Tween } from 'cc';
import UtilTool from '../../tools/UtilTool';
import { GameBaseModel } from './GameBaseModel';
import { BALL_RADIUS } from './GameManage';
import { TweenAction } from 'cc';
import { tween } from 'cc';
import { BallUI } from './BallUI';
import { find } from 'cc';
const { ccclass, property } = _decorator;

let DEFAULT_MASS = 0.16 // 球的质量

@ccclass('Ball')
export class Ball extends Component {

    // 世界坐标为0.365000

    static BALL_STATIC_Y = 0.435 //-0.366 // 球静止时的世界坐标值
    
    @property({type: [Material]})
    material : Material[] = []; 

    @property(Node)
    model : Node = null;

    defaultMask : number = 0;

    tag = ""

    size = 0

    number : number = 0

    defaultMaterial : Material = null
    sencondMaterial : Material = null

    meshRenderer : MeshRenderer = null

    defaultRotate : Vec3 = null // 默认旋转角度

    isHasInRole = false // 是否已经进洞

    isOrientation = false // 是否显示定位

    protected onLoad(): void {
        // 初始化碰撞器大小

        this.getComponent(RigidBody).useCCD = true // 开启连续碰撞检测;

        this.setSize(BALL_RADIUS * 2)

        this.meshRenderer = this.node.getChildByName("model").getComponent(MeshRenderer)
        
        this.node.getComponent(RigidBody).mass = DEFAULT_MASS // 球的质量

        this.defaultMaterial = this.meshRenderer.materials[0]
        this.sencondMaterial = this.meshRenderer.materials[1]

        this.defaultRotate = this.node.eulerAngles.clone()

    }

    start() {

        let group = this.node.getComponent(ColliderComponent).getGroup()
        let mask = this.node.getComponent(ColliderComponent).getMask()

        // this.node.getComponent(ColliderComponent).setGroup(GameGroup.G_BODY)
        // this.node.getComponent(ColliderComponent).setMask(-1)
        
        this.node.getComponent(ColliderComponent).on('onCollisionEnter', this.onCollisionEnter, this)
        
        this.defaultMask = mask;
        
    }

    setSize(size) {
        this.size = size
        
        let struct : Mesh.IStruct = this.model.getComponent(ModelComponent).mesh.struct;
        let scalex = size / Math.abs(struct.maxPosition.x - struct.minPosition.x)
        let scaley = size / Math.abs(struct.maxPosition.y - struct.minPosition.y)
        let scalez = size / Math.abs(struct.maxPosition.z - struct.minPosition.z)

        this.model.setWorldScale(new Vec3(scalex, scaley, scalez))
        // this.model.setPosition(new Vec3(0, size/2, 0))
        
        this.getComponent(SphereCollider).radius = this.size/2;

        this.getComponent(BoxCollider)

    }

    onCollisionEnter(event : ICollisionEvent) {

        if(event.otherCollider.node.name == "ball" || event.otherCollider.node.name == "whiteball") {
            UtilTool.printLog("ball collision")

            let body : RigidBody = event.otherCollider.node.getComponent(RigidBody)
            let velocity = new Vec3()
            body.getLinearVelocity(velocity)
            let force = velocity.length()

            // 根据力的大小来播放对应的音乐
            App.Audio.playOneShot("ball", true, this.getSoundVolume(force))

            // UtilTool.printLog("velocity", force)

            if(this.node.name == "whiteball") {
                if(event.otherCollider.node.name == "ball") {
                    
                    let otherBall = event.otherCollider.node.getComponent(Ball)
                    let number = otherBall.number
                    App.Event.emit(EventConst.WHITEBALL_CONTACT_BALL, number, otherBall)

                }
                
            }

        }
        else if (event.otherCollider.node.name == "wall") {
            let body : RigidBody = event.selfCollider.node.getComponent(RigidBody)
            let velocity = new Vec3()
            body.getLinearVelocity(velocity)
            let force = velocity.length()

            // 根据力的大小来播放对应的音乐
            App.Audio.playOneShot("board", true, this.getSoundVolume(force, 0.8))
        }

    }

    init(number, tag : string = "") {
        this.model.getComponent(MeshRenderer).setMaterial(this.material[number], 0);
        this.number = number
        this.tag = tag
    }

    // 设置默认状态
    setDefault() {

        if(this.defaultMask) {
            this.node.getComponent(ColliderComponent).setMask(this.defaultMask);
        }

        if(this.defaultRotate) {
            this.node.eulerAngles = this.defaultRotate
        }

        // this.meshRenderer.setMaterial(this.defaultMaterial, 0);
        // this.sencondMaterial.setProperty("opacity", 1)
    }

    // 设置透明
    setOpacity(opacity : number = 0.5) {
        this.meshRenderer.setMaterial(this.sencondMaterial, 0);
        this.sencondMaterial.setProperty("opacity", opacity)
    }

    getSize() : number {
        return this.size
    }   

    getWidth() : number {   
        return this.getSize()
    }

    hide() {
        this.reset()
        this.node.active = false

        if(this.node.name == "whiteball") {
            find("Canvas/viewNode/cueNode2d").active = false
        }

        // new Tween(this.node).delay(0.05).call(() => {
        //     this.node.getComponent(RigidBody).sleep() // 球休眠
        //     this.node.active = false
        // }).start()
        
    }

    reset() {
        this.node.getComponent(RigidBody).setLinearVelocity(new Vec3(0, 0, 0));
        this.node.getComponent(RigidBody).setAngularVelocity(new Vec3(0, 0, 0));
        // this.node.getComponent(RigidBody).applyImpulse(0)

        this.node.worldPosition = new Vec3(10000, this.node.worldPosition.y, 10000)
        this.node.getComponent(RigidBody).sleep() // 球休眠
    }

    /**
     * 设置呼吸节点的显示隐藏
     * @param show 是否显示
     */
    setAbelNode(show=false){
        let ballUI = App.Model.gameManage.otherBallArrUI[this.number-1]
        if (ballUI) {
            setTimeout(() => {
                if (ballUI) {
                    ballUI.getComponent(BallUI).setAbelNode(show, this.node.worldPosition)
                }
            }, 100);
        }
    }

    update(deltaTime: number) {

        let velocity = new Vec3()
        this.node.getComponent(RigidBody).getLinearVelocity(velocity)
        let velocityLength = velocity.length()

        let rangle = new Vec3()
        this.node.getComponent(RigidBody).getAngularVelocity(rangle)
        let rangleLength = rangle.length()
        
        // UtilTool.printLog("velocity", velocityLength, "rangle", rangleLength) 6

        // 当移动速度低于一个值是，则停止运动
        if( (/* velocityLength>0.001 && */ velocityLength<2) && rangleLength < 2.0 && !this.node.getComponent(RigidBody).isSleeping) {
            // this.node.getComponent(RigidBody).setLinearVelocity(new Vec3(0, 0, 0))
            // this.node.getComponent(RigidBody).setAngularVelocity(new Vec3(0, 0, 0))

            if(!this.isHasInRole) {
                this.node.getComponent(RigidBody).sleep()
            }

            // UtilTool.printLog("test ball", this.node.getComponent(RigidBody).isSleeping)
        }

        // 保持球在y轴上不能跳起来
        if(this.node.active) {
            if (Math.abs(this.node.worldPosition.y - Ball.BALL_STATIC_Y)>0.00001) {
                this.node.setWorldPosition(this.node.worldPosition.x, Ball.BALL_STATIC_Y, this.node.worldPosition.z)
            }
        }

        // 球运动的时候去掉定位
        if (this.isOrientation && !this.node.getComponent(RigidBody).isSleeping) {
            let gameView = App.Model.gameView as GameBaseModel
            gameView.setBallOrientation(false)
        }

        // if(this.number == 2) {
            // UtilTool.printLog("ball position", this.node.worldPosition.toString())
        // }

        // UtilTool.printLog("ball position", this.node.worldPosition.y)

        // if(this.node.name == "whiteball") {
        //     UtilTool.printLog("whiteball ball position", this.node.worldPosition.y, this.node.getComponent(RigidBody).isSleeping)
        // }


    }

    setWhiteBall(worldPos : Vec3) {
        if(this.node.name == "whiteball") {
            this.node.setWorldPosition(new Vec3(worldPos.x, this.node.worldPosition.y, worldPos.z))
            this.node.active = true
        }
    }

    /**
     * 获取球碰撞声音大小
     */
    getSoundVolume(velocity,ratio = 0.2) {
        let maxVelocity = 1875
        
        let volume = velocity / maxVelocity
        if(volume<ratio) {
            volume = ratio
        }
        
        return volume
    }

    protected onDestroy(): void {
        Tween.stopAllByTarget(this.node)
        Tween.stopAllByTarget(this)
    }

}

